<?php


namespace Core\server;

use Core\BeanFactory;
use Core\http\Request;
use Core\http\Response;
use Core\init\RouterCollect;
use Core\init\TestProcess;
use Swoole\Http\Server;

class HttpServer
{
    use ServerTrait;

    protected $server;

    protected $master_pid;
    protected $pid_file;
    protected $config;

    private $dispatcher;

    /**
     * HttpServer constructor.
     */
    public function __construct()
    {
        $this->pid_file = ROOT_PATH . '/tmp/phpfans.pid';
        $this->server = new Server('0.0.0.0', 9501);

        $this->config = [
            'worker_num' => 2,    //worker process num
            'backlog' => 128,   //listen backlog
            'max_request' => 50,
            'dispatch_mode' => 1,
        ];

        $this->server->set($this->config);

        $this->server->on('Start', [$this, 'onStart']);
        $this->server->on('WorkerStart', [$this, 'onWorkerStart']);
        $this->server->on('ManagerStart', [$this, 'onManagerStart']);
        $this->server->on("request", [$this, 'onRequest']);
        $this->server->on('ShutDown', [$this, 'onShutdown']);

//        $this->server->on('Start', [$this, 'onStart']);
//        $this->server->on('Shutdown', [$this, 'onShutdown']);
//        $this->server->on('ManagerStart', [$this, 'onManagerStart']);
//        $this->server->on('ManagerStop', [$this, 'onManagerStop']);
//        $this->server->on('WorkerStart', [$this, 'onWorkerStart']);
//        $this->server->on('WorkerStop', [$this, 'onWorkerStop']);
//        $this->server->on('WorkerError', [$this, 'onWorkerError']);
//        $this->server->on('PipeMessage', [$this, 'onPipeMessage']);
    }


    /**
     * 启动服务 start 回调
     * @param Server $server
     */
    public function onStart(Server $server)
    {
        $this->setProcessTitle('phpfans master');

        $this->master_pid = $server->master_pid;
        file_put_contents($this->pid_file, $this->master_pid);
    }

    public function onWorkerStart(Server $server, $workerId)
    {
        if ($workerId >= $this->config['worker_num']) {
            $process = 'task worker';
        } else {
            $process = 'worker';
            /*if (!empty($this->config['enable_coroutine_runtime'])) {
                \Swoole\Runtime::enableCoroutine();
            }*/
        }

        $this->setProcessTitle(sprintf('phpfans: %s process %d', $process, $workerId));


        //这里初始化 annotation 和 DI
        BeanFactory::init();
        $this->dispatcher = BeanFactory::getBean(RouterCollect::class)->getDispatcher();

        //清理掉其它缓存，以免发生不可预知问题
        if (function_exists('opcache_reset')) {
            opcache_reset();
        }
        if (function_exists('apc_clear_cache')) {
            apc_clear_cache();
        }
        if (function_exists('apcu_clear_cache')) {
            apcu_clear_cache();
        }

        clearstatcache();
    }

    /**
     * reload必须
     * @param Server $server
     * @param $workId
     */
    public function onManagerStart(Server $server)
    {
        $this->setProcessTitle('phpfans manager');
    }

    /**
     * onRequest
     * @param \Swoole\Http\Request $request
     * @param \Swoole\Http\Response $response
     */
    public function onRequest(\Swoole\Http\Request $request, \Swoole\Http\Response $response)
    {
        //使用自己封装的request  传入
        $fransRequest = Request::init($request);
        $fransResponse = Response::init($response);

        $routeInfo = $this->dispatcher->dispatch($fransRequest->getMethod(), $fransRequest->getUri());
        switch ($routeInfo[0]) {
            case \FastRoute\Dispatcher::NOT_FOUND:
                $response->status(404);
                $response->end("Method not found");
                break;
            case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
                $response->status(405);
                $response->end("Method not allow");

                break;
            case \FastRoute\Dispatcher::FOUND:
                $handler = $routeInfo[1];
                //file_put_contents(__DIR__ . '/' . date('Ymd') . '.log', __METHOD__ . " handler:" . json_encode($routeInfo) . "\r\n\n", FILE_APPEND);

                file_put_contents(__DIR__ . '/' . date('Ymd') . '.log', __METHOD__ . " router args:" . json_encode($routeInfo[2]) . "\r\n\n", FILE_APPEND);

                $bind_params = $routeInfo[2];
                $ext_params = [$fransRequest, $fransResponse];
                $data = $handler($bind_params, $ext_params);
                //file_put_contents(__DIR__ . '/' . date('Ymd') . '.log', __METHOD__ . " response :" . $data . "\r\n\n", FILE_APPEND);

                $fransResponse->setBody("输出的结果是：" . $data); //设置body体
                $fransResponse->end();
                break;
        }


    }

    /**
     *
     */
    public function onShutdown()
    {
        unlink($this->pid_file);
    }

    /**
     * 启动服务
     */
    public function run()
    {
        //增加自定义进程
        $ps = new TestProcess();
        $this->server->addProcess($ps->run());

        $this->server->start();
    }

}